home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1994
/
MacHack 1994.toast
/
MacHack™94
/
Talks & Papers
/
Michael D. Crawford↵
/
Word Services SDK 1.0.5
/
Writeswell Jr. Source
/
ObWind.c
< prev
next >
Wrap
Text File
|
1992-10-02
|
14KB
|
580 lines
/* ObWind.c
* Routines to handle cWindow objects
* ©1992 Working Software, Inc.
* This source code is copyrighted. Permission is granted to use the Word Services
* portion of the Writeswell Jr. source code in your own programs, but you
* may not distribute the Writeswell Jr. word-processor code as a
* commercial product. If you modify the code, please do not call it
* Writeswell Jr. (or Writeswell.) This will ensure that people understand the
* program and don’t have to deal with a number of different versions with
* who-knows-what going on in the code.
*
* Writeswell Jr. and Writeswell are trademarks of Working Software, Inc.
* 24 Dec 91 Mike Crawford
*/
#include <AppleEvents.h>
#include <AEObjects.h>
#include <AEPackObject.h>
#include <AERegistry.h>
#include "AppEvents.h"
#include "ObWind.h"
#include "ObText.h"
#include "ObOSpec.h"
#include "Gripe.h"
OSErr WindGetDataHandler( AEDesc *tokenPtr,
AppleEvent *theAppleEventPtr,
AppleEvent *replyEventPtr,
long refCon );
OSErr WindSetDataHandler( AEDesc *tokenPtr,
AppleEvent *theAppleEventPtr,
AppleEvent *replyEventPtr,
long refCon );
OSErr WindCountHandler( AEDesc *tokenPtr,
AppleEvent *theAppleEventPtr,
AppleEvent *replyEventPtr,
long refCon );
/* Given the the direct object of an event is a window token (or property thereof),
* do the requested event.
*/
OSErr DispatchWind( AEDesc *tokenPtr,
AppleEvent *theAppleEventPtr,
AppleEvent *replyEventPtr,
long refCon )
{
OSErr err;
AEEventClass theClass;
AEEventID theID;
/* This function is only for the Core suit. Get the event ID from the appleEvent
*/
err = GetEventID( theAppleEventPtr, &theID );
switch ( theID ){
case kAEGetData:
err = WindGetDataHandler( tokenPtr, theAppleEventPtr, replyEventPtr, refCon );
break;
case kAESetData:
err = WindSetDataHandler( tokenPtr, theAppleEventPtr, replyEventPtr, refCon );
break;
case kAECountElements:
err = WindCountHandler( tokenPtr, theAppleEventPtr, replyEventPtr, refCon );
default:
err = errAEEventNotHandled;
break;
}
return noErr;
}
/* The handlers for the various events */
/* Get Data */
OSErr WindGetDataHandler( AEDesc *tokenPtr,
AppleEvent *theAppleEventPtr,
AppleEvent *replyEventPtr,
long refCon )
{
WindowPtr wp;
DescType propCode;
WindTokenBody **tokHdl;
AEDesc replyValue;
Str255 tmpStr;
OSErr err;
/* Sanity check */
if ( tokenPtr->descriptorType != cWindow ){
Gripe( "\pGot wrong token type" );
return errAEEventNotHandled;
}
tokHdl = (WindTokenBody**)(tokenPtr->dataHandle);
wp = (*tokHdl)->theWindowPtr;
propCode = (*tokHdl)->propertyCode;
if ( !wp ){
Gripe( "\pAttempting to get data for non-existent window" );
return errAENoSuchObject;
}
switch ( propCode ){
case typeNull:
/* This is a magic number for "Not A Property". I don't know if this
* is really kosher - gotta ask, but it is a convenience.
*/
/* Should return a string for object browsers */
Gripe( "\pTrying to GetData on a window object" );
return errAENoSuchObject;
break;
case pName:
GetWTitle( wp, tmpStr );
err = AECreateDesc( typeChar,
(Ptr)&(tmpStr[1]),
(Size)tmpStr[0],
&replyValue );
if ( err ){
Gripe( "\pAECreateDesc failed" );
return err;
}
break;
case pBounds:
case pClass:
case pHasTitleBar:
case pIndex:
case pIsModal:
case pIsResizable:
case pIsZoomed:
case pVisible:
Gripe( "\pGot a property type we do not yet implement" );
return errAENoSuchObject;
break;
default:
Gripe( "\pUnknown property type" );
return errAENoSuchObject;
break;
}
/* At this point we have some kind of descriptor to stick in the reply */
err = AEPutParamDesc( replyEventPtr,
keyDirectObject,
&replyValue );
if ( err ){
Gripe( "\pAEPutParamDesc failed" );
return err;
}
err = AEDisposeDesc( &replyValue );
if ( err ){
Gripe( "\pAEDisposeDesc failed" );
return err;
}
return noErr;
}/* WindGetDataHandler */
/* Set Data */
OSErr WindSetDataHandler( AEDesc *tokenPtr,
AppleEvent *theAppleEventPtr,
AppleEvent *replyEventPtr,
long refCon )
{
WindowPtr wp;
DescType propCode;
WindTokenBody **tokHdl;
AEDesc newValue;
AEDesc textValue;
OSErr err;
/* Sanity check */
if ( tokenPtr->descriptorType != cWindow ){
Gripe( "\pGot wrong token type" );
return errAEEventNotHandled;
}
tokHdl = (WindTokenBody**)(tokenPtr->dataHandle);
wp = (*tokHdl)->theWindowPtr;
propCode = (*tokHdl)->propertyCode;
if ( !wp ){
Gripe( "\pAttempting to set data in non-existent window" );
return errAENoSuchObject;
}
/* Get the value to set, whatever it is */
err = AEGetParamDesc( theAppleEventPtr,
keyAEData,
typeWildCard,
&newValue );
if ( err ){
Gripe( "\pAEGetParamDesc failed to get keyAEData" );
return err;
}
switch ( propCode ){
case typeNull:
/* This is a magic number for "Not A Property". I don't know if this
* is really kosher - gotta ask, but it is a convenience.
*/
/* I don't think it makes sense to Set Data on a window */
return errAEEventNotHandled;
break;
case pName:
/* Make sure that the name is of type text */
err = AECoerceDesc( &newValue,
typePString,
&textValue );
if ( err ){
Gripe( "\pAECoerceDesc failed to coerce to text" );
return err;
}
HLock( textValue.dataHandle );
SetWTitle( wp, *(textValue.dataHandle) );
HUnlock( textValue.dataHandle );
err = AEDisposeDesc( &textValue );
if ( err ){
Gripe( "\pAEDisposeDesc textValue failed" );
return err;
}
break;
case pBounds:
case pClass:
case pHasTitleBar:
case pIndex:
case pIsModal:
case pIsResizable:
case pIsZoomed:
case pVisible:
Gripe( "\pGot a property type we do not yet implement" );
return errAENoSuchObject;
break;
default:
Gripe( "\pUnknown property type" );
return errAENoSuchObject;
break;
}
/* At this point we are done with the newValue descriptor */
err = AEDisposeDesc( &newValue );
if ( err ){
Gripe( "\pAEDisposeDesc newValue failed" );
return err;
}
return noErr;
}/* WindSetDataHandler */
/* Count Elements */
OSErr WindCountHandler( AEDesc *tokenPtr,
AppleEvent *theAppleEventPtr,
AppleEvent *replyEventPtr,
long refCon )
{
WindowPtr wp;
DescType propCode;
WindTokenBody **tokHdl;
AEDesc replyValue;
Str255 tmpStr;
AEDesc elementClassDesc;
DescType elementClass;
long count;
OSErr err;
/* Sanity check */
if ( tokenPtr->descriptorType != cWindow ){
Gripe( "\pGot wrong token type" );
return errAEEventNotHandled;
}
tokHdl = (WindTokenBody**)(tokenPtr->dataHandle);
wp = (*tokHdl)->theWindowPtr;
propCode = (*tokHdl)->propertyCode;
if ( !wp ){
Gripe( "\pAttempting to count elements for non-existent window" );
return errAENoSuchObject;
}
/* Get the class of element that we want to count. We could reasonably
* count the letters of the title property, for example. Presently we
* only support counting the object specifier elements for the word services
* table checking method.
*/
err = AEGetParamDesc( theAppleEventPtr,
keyAEObjectClass,
typeType,
&elementClassDesc );
if ( err ){
Gripe( "\pCould not get object class from Count Elements event" );
return err;
}
elementClass = *(DescType*)(*elementClassDesc.dataHandle);
switch ( propCode ){
case typeNull:
/* This is a magic number for "Not A Property". I don't know if this
* is really kosher - gotta ask, but it is a convenience.
*/
/* In this case, we are counting the actual elements of the window. This
* can be a text field or an object specifier. We check to see what
* kind of element is desired, and call a function for that class to count
* it.
*
* We do not yet handle the case where we could have multiple containers.
*/
switch ( elementClass ){
case cText:
err = CountTextInWind( wp, &count );
if ( err )
return err;
break;
case typeObjectSpecifier:
err = CountOSpecInWind( wp, &count );
if ( err )
return err;
break;
default:
return errAENoSuchObject;
break;
}
err = AECreateDesc( typeLongInteger, (Ptr)&count, sizeof( count ), &replyValue );
if ( err ){
Gripe( "\pAECreateDesc failed" );
return err;
}
break;
case pName:
case pBounds:
case pClass:
case pHasTitleBar:
case pIndex:
case pIsModal:
case pIsResizable:
case pIsZoomed:
case pVisible:
/* In all of these cases, we are counting the elements of a property.
* This makes more sense than it might seem. It is reasonable to count
* the letters in the name, for example.
*/
Gripe( "\pGot a property type we do not yet implement" );
return errAENoSuchObject;
break;
default:
Gripe( "\pUnknown property type" );
return errAENoSuchObject;
break;
}
/* At this point we have some kind of descriptor to stick in the reply */
err = AEPutParamDesc( replyEventPtr,
keyDirectObject,
&replyValue );
if ( err ){
Gripe( "\pAEPutParamDesc failed" );
return err;
}
err = AEDisposeDesc( &replyValue );
if ( err ){
Gripe( "\pAEDisposeDesc failed" );
return err;
}
return noErr;
}
/* Return a Window token given a null (application) token */
pascal OSErr WindFromNull(DescType desiredClass,
const AEDesc *container,
DescType containerClass,
DescType form,
const AEDesc *selectionData,
AEDesc *theToken,
long LongInt)
{
AEDesc longKeyData;
WindowPtr wp;
long count;
WindTokenBody tokData;
OSErr err;
/* Check that the container is what we intend. This should only happen if we
* installed the token handler incorrectly.
*/
if ( container->descriptorType != typeNull )
return errAEEventNotHandled;
/* find the window based on the key form */
switch ( form ){
case formAbsolutePosition:
/* Make sure we really have a type long descriptor */
err = AECoerceDesc( selectionData, typeLongInteger, &longKeyData );
if ( err ){
Gripe( "\pAECoerceDesc failed" );
return err;
}
count = **(long**)(longKeyData.dataHandle);
/* We're done with the descriptor created in the coercion */
err = AEDisposeDesc( &longKeyData );
if ( err ){
Gripe( "\pAEDisposeDesc failed" );
return err;
}
/* In our particular case, we can have at most one window, but we write
* this in a general way for reusability... scan the window list for the
* window
*/
wp = FrontWindow();
while( count > 1 && wp != (WindowPtr)NULL ){
wp = (WindowPtr)((WindowPeek)wp)->nextWindow;
}
if ( wp == (WindowPtr)NULL ){
Gripe( "\pNo window found" );
return errAENoSuchObject;
}
/* Actually create the token that we return */
tokData.theWindowPtr = wp;
tokData.propertyCode = typeNull; /* This means it's not a property */
err = AECreateDesc( desiredClass, (Ptr)&tokData, sizeof( tokData ), theToken );
if ( err ){
Gripe( "\pAECreateDesc failed to create a token" );
return err;
}
return noErr;
break;
case formRelativePosition:
case formTest:
case formRange:
case formPropertyID:
case formName:
return errAEEventNotHandled; /* Flesh this out later */
break;
default:
Gripe( "\pGot unexpected key form" );
return errAEEventNotHandled;
}
return noErr;
}
/* Return a property token given a cWindow token. This works for any property of a window */
pascal OSErr PropFromWind(DescType desiredClass,
const AEDesc *container,
DescType containerClass,
DescType form,
const AEDesc *selectionData,
AEDesc *theToken,
long LongInt)
{
OSErr err;
DescType propType;
/* Check that the container is what we intend. This should only happen if we
* installed the token handler incorrectly.
*/
if ( container->descriptorType != cWindow )
return errAEEventNotHandled;
if ( form != formPropertyID ){
Gripe( "\pExpected formPropertyID" );
return errAEEventNotHandled;
}
propType = **( (DescType**)(selectionData->dataHandle) );
/* All we really do here is shove the property type into the token, if we
* know about the property type
*/
switch ( propType ){
case pName:
break;
case pBounds:
case pClass:
case pHasTitleBar:
case pIndex:
case pIsModal:
case pIsResizable:
case pIsZoomed:
case pVisible:
Gripe( "\pGot a property type we do not yet implement" );
return errAENoSuchObject;
break;
default:
Gripe( "\pUnknown property type" );
return errAENoSuchObject;
break;
}
/* All we do in the token is put the propType into it. We can start with the
* container descriptor as it has some of the fields filled in already.
*/
err = AEDuplicateDesc( container, theToken );
if ( err ){
Gripe( "\pAEDuplicateDesc failed" );
return err;
}
(*(WindTokenBody**)(theToken->dataHandle))->propertyCode = propType;
return noErr;
}
/*
* Descriptor packing routines
*/
/* Create a formAbsolutePosition window descriptor */
OSErr BuildWindowSpecifier( AEDesc *specPtr, long whichWindow )
{
AEDesc nullDesc;
AEDesc nullSpec;
AEDesc whichDesc;
OSErr err;
/* Create the descriptor for the container (the application, or null) */
err = AECreateDesc( typeNull, (Ptr)NULL, (Size)0, &nullDesc );
if ( err )
return err;
/* Create the key data, which gives the window number */
err = CreateOffsetDescriptor( whichWindow, &whichDesc );
if ( err )
return err;
/* Create the Object Specifier for the window */
err = CreateObjSpecifier( cWindow,
&nullDesc,
formAbsolutePosition,
&whichDesc,
true, /* Dispose of input descriptors */
specPtr ); /* specPtr is the value we return */
return err;
}